//
// HTTPUpdater
//
// Copyright (C) jextra.net.
//
//  This file is part of the Crack build system.
//
//  The Crack build system is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The Crack build system is distributed in the hope that it will be 
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the Crack build system; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.crack.updater;

import java.io.*;
import java.net.*;
import java.util.*;
import net.jextra.crack.*;
import net.jextra.crack.tool.*;
import net.jextra.crack.updater.http.*;

/**
 * Web service, XML based Crack Updater.
 */
public class HTTPUpdater implements CrackUpdater
{
    // ============================================================
    // Fields
    // ============================================================

    public static final int CONNECTION_TIMEOUT = 10000;

    private String name;
    private URL rootURL;
    private int timeout = CONNECTION_TIMEOUT;

    // ============================================================
    // Constructors
    // ============================================================

    public HTTPUpdater( URL rootURL )
    {
        this.rootURL = rootURL;
    }

    /**
     * Should be used only by a UpdaterFactory.
     */
    protected HTTPUpdater()
    {
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    @Override
    public void init( CrackUpdaterParams params )
    {
        try
        {
            name = params.getAttribute( "name" );
            rootURL = new URL( params.getAttribute( "url" ) );
            if ( name == null )
            {
                name = rootURL.toString();
            }
            String timeoutString = params.getAttribute( "timeout" );
            if ( timeoutString != null )
            {
                timeout = Integer.parseInt( timeoutString );
            }
        }
        catch ( Exception ex )
        {
            throw new CrackException( ex );
        }
    }

    @Override
    public URL getRootURL()
    {
        return rootURL;
    }

    @Override
    public String getName()
    {
        return name;
    }

    @Override
    public int getTimeout()
    {
        return timeout;
    }

    @Override
    public List<CrackUpdaterEntry> getEntries( String path )
        throws Exception
    {
        CrackUpdaterEntriesReader reader = new CrackUpdaterEntriesReader();
        InputStream in = getInputStream( "list/" + path );
        reader.parse( in );
        in.close();

        return reader.getEntries();
    }

    @Override
    public CrackUpdaterEntry getEntry( String path )
        throws Exception
    {
        List<CrackUpdaterEntry> entries = getEntries( path );

        return entries == null || entries.isEmpty() ? null : entries.get( entries.size() - 1 );
    }

    @Override
    public URL getFileURL( String path )
        throws MalformedURLException
    {
        return buildURL( "download/" + path );
    }

    @Override
    public void uploadFile( String path, File localFile )
        throws Exception
    {
        try
        {
            URLConnection conn = buildURL( "upload/" + path ).openConnection();
            conn.setConnectTimeout( getTimeout() );
            conn.setReadTimeout( getTimeout() );
            HTTPPost post = new HTTPPost( conn );
            post.addParameter( "file", localFile );
            post.execute();
        }
        catch ( Exception ex )
        {
            throw new CrackException( ex );
        }
    }

    // ----------
    // private
    // ----------

    private InputStream getInputStream( String url )
    {
        try
        {
            URLConnection conn = buildURL( url ).openConnection();
            conn.setConnectTimeout( getTimeout() );
            conn.setReadTimeout( getTimeout() );
            conn.connect();
            InputStream in = conn.getInputStream();

            return in;
        }
        catch ( Exception ex )
        {
            throw new CrackError( "Unable to connect to updater [%s].", rootURL );
        }
    }

    private URL buildURL( String path )
        throws MalformedURLException
    {
        return new URL( mergePath( rootURL.toString(), path ) );
    }

    private String mergePath( String prefix, String suffix )
    {
        String string = prefix.replace( '\\', '/' );

        if ( !string.endsWith( "/" ) )
        {
            string += "/";
        }

        string += suffix;

        return string;
    }
}
